/*
 * Parser.scala
 */

package acorn.jash

import acorn.jash.io.Sink
// import acorn.jash.io.Pipe

class Parser {
  def parse(arg:String):Expr = {
    val li = p2(arg)
    p3(li.head, li.tail)
  }


  private def p1(arg:String):List[String] = {
    val tr = arg trim;
    for (i <- 0 until tr.length) {
      tr.charAt(i) match {
        case ' ' => return tr.substring(0,i)::p1(tr.substring(i+1))
        case _ => 
      }
    }
    tr::Nil
  }


  private def p2(arg:String):List[List[String]] = {
    val tr = arg trim;
    for (i <- 0 until tr.length) {
      tr.charAt(i) match {
        case '|' => return p1(tr.substring(0,i))::p2(tr.substring(i+1))
        case _ =>
      }
    }
    List(p1(tr))
  }


  private def p3(arg1:List[String], args:List[List[String]]):ChainedExpr = {
    val cmd = new ChainedExpr(newExpr(arg1))
    args match {
      case Nil => cmd
      case _ => {
        cmd.next = p3(args.head, args.tail);

        val p = new Sink
        cmd.expr.out = p
        cmd.next.expr.in = p

        cmd
      }
    }
  }


  private def newExpr(args:List[String]):Expr = {
    Shell.debug("args(0) => " + args(0))
    val expr = newExpr(args(0))
    var rout, rin = false
    args.tail.foreach{_ match {
      case ">" => rout = true
      case "<" => rin = true
      case s:String => {
        val ts = if (s startsWith "-") s else Path translate s;
        Shell.debug("s => " + s + ", ts => " + ts);
        if (rout) {
          rout = false
          import acorn.jash.io.FileOutput
          expr.out = new FileOutput(ts)
        }
        else if (rin) {
          rin = false
        }
        else {
          expr.args = (ts::expr.args)
        }
      }
    }}

    expr.args = expr.args.reverse
    expr
  }


  private def newExpr(cmd:String):Expr = {
    try {
      val clz = "acorn.jash.commands." + cmd
      Class.forName(clz).newInstance().asInstanceOf[Expr]
    }
    catch {
      case e:ClassNotFoundException => new SimpleCmd(true, Path translate cmd)
    }
  }
}



